#include "manhatline.h"
#include <cstdlib>
#include <cmath>
#include <iostream>


manhattan_line_t::manhattan_line_t(point_t const & start, point_t const & end) : start_(start),
        end_(end)
{
}

double manhattan_line_t::intersects(segment_t const & seg, manhattan_part_t part) const
{
    line_t seg_line(seg.first, seg.second);
    if (part == VERT_PART || (part == BASE_PART && end_.y != start_.y))
    {
        if(seg_line.is_vertical())
            return -1;
        if(seg_line.is_horizontal())
        {
            if(start_.x <= std::max(seg.first.x, seg.second.x) && start_.x >= std::min(seg.first.x, seg.second.x)
                    && seg.first.y <= std::max(start_.y, end_.y) && seg.first.y >= std::min(start_.y, end_.y))
                return abs(start_.y - seg.first.y);
            return -1;
        }

        double y = seg_line.get_y(start_.x);
        if (y <= std::max(seg.first.y, seg.second.y) + 0.000001 && y >= std::min(seg.first.y, seg.second.y) - 0.000001
                && y <= std::max(start_.y, end_.y) + 0.000001 && y >= std::min(start_.y, end_.y) - 0.000001)
        {
            return abs(y - start_.y);
        }
        return -1;
    }

    if (part == HOR_PART || (part == BASE_PART && end_.y == start_.y))
    {
        if(seg_line.is_horizontal())
            return -1;
        if(seg_line.is_vertical())
        {
            if(end_.y <= std::max(seg.first.y, seg.second.y) && end_.y >= std::min(seg.first.y, seg.second.y)
                    && seg.first.x <= std::max(start_.x, end_.x) && seg.first.x >= std::min(start_.x, end_.x))
                return abs(start_.x - seg.first.x);
            return -1;
        }

        double x = seg_line.get_x(end_.y);
        if (x <= std::max(seg.first.x, seg.second.x) && x >= std::min(seg.first.x, seg.second.x)
                && x <= std::max(start_.x, end_.x) && x >= std::min(start_.x, end_.x))
        {
            return abs(x - start_.x);
        }
    }
    return -1;
}

segment_t manhattan_line_t::part(manhattan_part_t p) const
{
    if (p == VERT_PART)
        return vert_seg();
    if (p == HOR_PART)
        return hor_seg();
    return base_seg();
}

segment_t manhattan_line_t::base_seg() const
{
    return segment_t(start_, end_);
}

segment_t manhattan_line_t::vert_seg() const
{
    return segment_t(start_, point_t(start_.x, end_.y));
}

segment_t manhattan_line_t::hor_seg() const
{
    return segment_t(point_t(start_.x, end_.y), end_);
}

point_t manhattan_line_t::corner() const
{
    return point_t(start_.x, end_.y);
}
